package com.uboxol.example.tengu.aop;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 临时使用 xml 兼容过渡
 *
 * @author liyunde
 * @date 16/4/6
 * <p>
 */
@Slf4j
@Aspect
@Component
public class LogHandlerInterceptor {

    private final ObjectMapper mapper;

    @Autowired
    public LogHandlerInterceptor(ObjectMapper mapper) {
        this.mapper = mapper.copy();
        this.mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
    }

    @Around("handlePointCut()")
    public Object doService(ProceedingJoinPoint point) throws Throwable {

        long t = System.currentTimeMillis();

        String rs = null;

        try {

            Object ret = point.proceed();

            if (ret != null) {
                if (!(ret instanceof String)) {
                    try {
                        rs = mapper.writeValueAsString(ret);
                    } catch (Exception e) {
                        rs = e.getMessage();
                        logger.error("结果不能正确转化:{}", e.getMessage(), e);
                    }
                } else {
                    rs = (String) ret;
                }
            }

            return ret;

        } catch (Throwable e) {

            logger.error("{} {} {} {} {}", point.getTarget().getClass().getSimpleName(), point.getSignature().getName(),
                         System.currentTimeMillis() - t, point.getArgs(), e.getMessage());

            throw e;
        } finally {

            if (null == rs) {
                logger.warn("{} {} {} {} null", point.getTarget().getClass().getSimpleName(),
                            point.getSignature().getName(), System.currentTimeMillis() - t, point.getArgs());
            } else {
                logger.info("{} {} {} {} {}", point.getTarget().getClass().getSimpleName(),
                            point.getSignature().getName(), System.currentTimeMillis() - t, point.getArgs(), rs);
            }
        }
    }

    // @AfterThrowing(value = "baseManagerMethod()", throwing = "ex")
    public void doThrowing(JoinPoint point, Throwable ex) {
        logger.error("{} {} {} {} {}", point.getTarget().getClass().getSimpleName(),
                     point.getSignature().getName(), 0, point.getArgs(), ex.toString());
    }

    @Pointcut("execution(* com.uboxol.example.tengu.api..*.*(..))")
    private void handlePointCut() {
    }

}
